#ifndef __JOB_HPP
#define __JOB_HPP

#include ".\Object.hpp"
#include ".\Handle.hpp"

class cJob : public cObject< cSubHandle >
{
public:
	bool Create( LPSECURITY_ATTRIBUTES lpJobAttributes, LPCTSTR lpName )
	{
		HANDLE job_handle = CreateJobObject( lpJobAttributes, lpName );
		if( job_handle == NULL )
			return false;
		cSubHandle *sub_handle;
		try
		{
			sub_handle = new cSubHandle( job_handle );
		}
		catch( ... )
		{
			return false;
		}
		SwitchToSubObject( sub_handle );
		return true;
	}
	operator HANDLE() const
	{
		if( GetSubObject() == NULL )
			return INVALID_HANDLE_VALUE;
		return GetSubObject()->Handle();
	}
	BOOL SetInformationJobObject( JOBOBJECTINFOCLASS JobObjectInfoClass, LPVOID lpJobObjectInfo, DWORD cbJobObjectInfoLength )
	{
		if( GetSubObject() == NULL )
			return FALSE;
		return ::SetInformationJobObject( GetSubObject()->Handle(), JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength );
	}
	BOOL QueryInformationJobObject( JOBOBJECTINFOCLASS JobObjectInfoClass, LPVOID lpJobObjectInfo, DWORD cbJobObjectInfoLength, LPDWORD lpReturnLength )
	{
		if( GetSubObject() == NULL )
			return FALSE;
		return ::QueryInformationJobObject( GetSubObject()->Handle(), JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength, lpReturnLength );
	}
	BOOL AssignProcess( HANDLE hProcess )
	{
		if( GetSubObject() == NULL )
			return FALSE;
		return ::AssignProcessToJobObject( GetSubObject()->Handle(), hProcess );
	}
};

struct sJobObjectExtendedLimitInformation : public JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
	sJobObjectExtendedLimitInformation( long long per_process_user_time_limit, long long per_job_user_time_limit, DWORD limit_flags, SIZE_T minimum_working_set_size, SIZE_T maximum_working_set_size, DWORD active_process_limit, ULONG_PTR affinity, DWORD priority_class, DWORD scheduling_class, SIZE_T process_memory_limit, SIZE_T job_memory_limit )
	{
		BasicLimitInformation.PerProcessUserTimeLimit.QuadPart = per_process_user_time_limit;
		BasicLimitInformation.PerJobUserTimeLimit.QuadPart = per_job_user_time_limit;
		BasicLimitInformation.LimitFlags = limit_flags;
		BasicLimitInformation.MinimumWorkingSetSize = minimum_working_set_size;
		BasicLimitInformation.MaximumWorkingSetSize = maximum_working_set_size;
		BasicLimitInformation.ActiveProcessLimit = active_process_limit;
		BasicLimitInformation.Affinity = affinity;
		BasicLimitInformation.PriorityClass = priority_class;
		BasicLimitInformation.SchedulingClass = scheduling_class;
		ProcessMemoryLimit = process_memory_limit;
		JobMemoryLimit = job_memory_limit;
	}
};

/*class cSubJobObjectExtendedLimitInformation : public cSubObject
{
	sJobObjectExtendedLimitInformation JobObjectExtendedLimitInformation;
public:
	cSubJobObjectExtendedLimitInformation( long long per_process_user_time_limit, long long per_job_user_time_limit, DWORD limit_flags, SIZE_T minimum_working_set_size, SIZE_T maximum_working_set_size, DWORD active_process_limit, ULONG_PTR affinity, DWORD priority_class, DWORD scheduling_class, SIZE_T process_memory_limit, SIZE_T job_memory_limit )
		: JobObjectExtendedLimitInformation( per_process_user_time_limit, per_job_user_time_limit, limit_flags, minimum_working_set_size, maximum_working_set_size, active_process_limit, affinity, priority_class, scheduling_class, process_memory_limit, job_memory_limit )
	{
	}
	~cSubJobObjectExtendedLimitInformation()
	{
	}
	PJOBOBJECT_EXTENDED_LIMIT_INFORMATION Pointer()
	{
		return &JobObjectExtendedLimitInformation;
	}
};

class cJobObjectExtendedLimitInformation
{
	cSubJobObjectExtendedLimitInformation *SubJobObjectExtendedLimitInformation;
public:
	cJobObjectExtendedLimitInformation( long long per_process_user_time_limit, long long per_job_user_time_limit, DWORD limit_flags, SIZE_T minimum_working_set_size, SIZE_T maximum_working_set_size, DWORD active_process_limit, ULONG_PTR affinity, DWORD priority_class, DWORD scheduling_class, SIZE_T process_memory_limit, SIZE_T job_memory_limit )
		: SubJobObjectExtendedLimitInformation( new cSubJobObjectExtendedLimitInformation( per_process_user_time_limit, per_job_user_time_limit, limit_flags, minimum_working_set_size, maximum_working_set_size, active_process_limit, affinity, priority_class, scheduling_class, process_memory_limit, job_memory_limit ) )
	{
	}
	cJobObjectExtendedLimitInformation( class cJobObjectExtendedLimitInformation &job_object_extended_limit_information )
		: SubJobObjectExtendedLimitInformation( job_object_extended_limit_information.SubJobObjectExtendedLimitInformation )
	{
		SubJobObjectExtendedLimitInformation->Attach();
	}
	~cJobObjectExtendedLimitInformation()
	{
		SubJobObjectExtendedLimitInformation->Detach();
	}
	cJobObjectExtendedLimitInformation &operator =( const cJobObjectExtendedLimitInformation &job_object_extended_limit_information )
	{
		SubJobObjectExtendedLimitInformation->Detach();
		SubJobObjectExtendedLimitInformation = job_object_extended_limit_information.SubJobObjectExtendedLimitInformation;
		SubJobObjectExtendedLimitInformation->Attach();
	}
	PJOBOBJECT_EXTENDED_LIMIT_INFORMATION Pointer()
	{
		return SubJobObjectExtendedLimitInformation->Pointer();
	}
};
/**/

struct sJobObjectBasicUIRestrictions : public JOBOBJECT_BASIC_UI_RESTRICTIONS
{
	sJobObjectBasicUIRestrictions( DWORD u_i_restrictions_class )
	{
		UIRestrictionsClass = u_i_restrictions_class;
	}
};

/*class cSubJobObjectBasicUIRestrictions : public cSubObject
{
	sJobObjectBasicUIRestrictions JobObjectBasicUIRestrictions;
public:
	cSubJobObjectBasicUIRestrictions( DWORD u_i_restrictions_class )
		: JobObjectBasicUIRestrictions( u_i_restrictions_class )
	{
	}
	~cSubJobObjectBasicUIRestrictions()
	{
	}
	PJOBOBJECT_BASIC_UI_RESTRICTIONS Pointer()
	{
		return &JobObjectBasicUIRestrictions;
	}
};

class cJobObjectBasicUIRestrictions 
{
	cSubJobObjectBasicUIRestrictions *SubJobObjectBasicUIRestrictions;
public:
	cJobObjectBasicUIRestrictions( DWORD u_i_restrictions_class )
		: SubJobObjectBasicUIRestrictions( new cSubJobObjectBasicUIRestrictions( u_i_restrictions_class ) )
	{
	}
	cJobObjectBasicUIRestrictions( const cJobObjectBasicUIRestrictions &job_object_basic_u_i_restrictions )
		: SubJobObjectBasicUIRestrictions( job_object_basic_u_i_restrictions.SubJobObjectBasicUIRestrictions )
	{
		SubJobObjectBasicUIRestrictions->Attach();
	}
	~cJobObjectBasicUIRestrictions()
	{
		SubJobObjectBasicUIRestrictions->Detach();
	}
	cJobObjectBasicUIRestrictions &operator =( const cJobObjectBasicUIRestrictions &job_object_basic_u_i_restrictions )
	{
		SubJobObjectBasicUIRestrictions->Detach();
		SubJobObjectBasicUIRestrictions = job_object_basic_u_i_restrictions.SubJobObjectBasicUIRestrictions;
		SubJobObjectBasicUIRestrictions->Attach();
	}
	PJOBOBJECT_BASIC_UI_RESTRICTIONS Pointer()
	{
		return SubJobObjectBasicUIRestrictions->Pointer();
	}
};/**/

#endif
